from django.shortcuts import render

# Create your views here.
from rest_framework.response import Response

from goods.models import SKU
from users.models import User
from users.utils import check_active_token

"""
一.确定需求
二.把需求拆分成我们的步骤
三.确定请求方式和url
四.确定视图,实现代码

前端当光标移开的时候,发送一个ajax请求,这个请求需要携带用户注册的用户名

1.接收参数
2.判断用户名是否注册(存在)
3.返回响应

GET        /users/usernames/(?P<username>\w{5,20})/count/


"""
# APIView
# GenericAPIView          对列表和详情视图做了通用支持,一般和mixin配合使用
# ListAPIView,RetriveAPIView
from rest_framework.views import APIView

class RegisterUsernameView(APIView):

    def get(self,request,username):

        # 1.接收参数
        # 2.判断用户名是否注册(存在)
        #查询用户名,根据返回的count值来判断
        #count = 0 表示没有注册
        #count = 1 表示注册了
        count = User.objects.filter(username=username).count()

        # 3.返回响应
        return Response({'count':count,'username':username})


"""
用户点击注册按钮的时候,前端需要将6个参数(mobile,password,password2,
username,sms_code,allow)传递给后端

1.接收参数
2.校验参数
3.数据入库
4.返回响应

"""
# APIView
# GenericAPIView          对列表和详情视图做了通用支持,一般和mixin配合使用
# CreateAPIView
#可以用二级视图和CreateModelMinxin,也可以用三级视图
from .serializers import RegisterCreateUserSerializer


class RegisterCreateUserView(APIView):

    def post(self,request):

        # 1.接收参数
        data = request.data
        # 2.校验参数 --->序列化器中
        serializer = RegisterCreateUserSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        # 3.数据入库
        serializer.save()
        # 4.返回响应
        # serializer.data
        # 序列化操作,将对象转为字典
        # 序列化的操作是根据序列化器的字段,去获取模型中的数据,来转换为字典

        #serializer.data 在进行序列化操作
        #serializer.data中没有token
        # 序列化的操作是根据序列化器的字段,去获取模型中的数据,来转换为字典
        #序列化器中没有token,我们就去加一个token
        #模型中没有,在模型中加一个token
        return Response(serializer.data)

"""
当用户完成注册之后,让用户自动登录

当用户完成注册之后,我们要返回一个token

1.在注册成功之后返回token
2.token没有,不知道怎么生成

"""
# APIView
#GenericAPIView                     列表,视图做了通用支持,一般和mixin配置使用
#ListAPIView,RetrieveAPIView
from rest_framework.permissions import IsAuthenticated
from .serializers import UserCenterInfoSerializer
from rest_framework.generics import RetrieveAPIView
# class UserCenterInfoView(APIView):
#     """
#         个人中心界面只能是 登录用户访问, 前端 通过在header中 添加token
#
#         # 1. 这个接口只能用登录用户访问
#         # 2. 获取登录用户的信息 user
#         # 3. 创建序列化器
#         # 4. 返回数据
#
#         GET     users/infos/
#
#     """
#
#     # 1. 这个接口只能用登录用户访问
#     permission_classes = [IsAuthenticated]
#     def get(self,request):
#
#         # 2. 获取登录用户的信息 user
#         user = request.user
#         # 3. 创建序列化器
#         serializer = UserCenterInfoSerializer(user)
#         # 4. 返回数据
#         return Response(serializer.data)
#用三级视图实现个人信息获取的第二种方式
class UserCenterInfoView(RetrieveAPIView):
    serializer_class = UserCenterInfoSerializer

    # queryset = User.objects.all()
    #权限
    permission_classes = [IsAuthenticated]

    #获取对象通过self.get_object,它通过pk来获取指定的数据信息,
    #重写get_object
    def get_object(self):

        return self.request.user

# APIView
#GenericAPIView                     列表,视图做了通用支持,一般和mixin配置使用
#UpdateAPIView
from rest_framework.generics import UpdateAPIView
from .serializers import UserUpdateEmailSerializer
# class UserUpdateEmailView(APIView):
#
#     """
#     用户填写完邮箱之后,点击保存,前端应该将email额token发送给后端
#     1.接收数据
#     2.对数据进行校验
#     3.更新数据
#     4.发送激活邮件
#     5.返回响应
#
#     PUT     /users/emails/
#
#     """
#     def put(self,request):
#
#         # 1.接收数据
#         data = request.data
#         user = request.user
#         # 2.对数据进行校验
#         serializer = UserUpdateEmailSerializer(instance=user,data=data)
#         serializer.is_valid(raise_exception=True)
#         # 3.更新数据
#         serializer.save()
#         # 4.发送激活邮件
#         # 5.返回响应
#         return Response(serializer.data)

#保存邮件信息采用三级视图
class UserUpdateEmailView(UpdateAPIView):
    serializer_class = UserUpdateEmailSerializer

    def get_object(self):

        return self.request.user


#邮件激活
from rest_framework import status
class UserEmailActiveView(APIView):

    """
    用户点击激活按钮,跳转到前端页面,前端页面就可以获取到token
    前端获取到token以后,需要将token发送给后端

    1.接收token
    2.对token进行解密,获取id
    3.根据Id获取用户信息
    4.修改用户的激活状态
    5.返回响应

    GET     /users/emails/verification/?token=xxx

    """

    def get(self,request):

        # 1.接收token
        token = request.query_params.get('token')
        if token is None:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # 2.对token进行解密,获取id
        user_id = check_active_token(token)
        if user_id is None:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # 3.根据Id获取用户信息
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # 4.修改用户的激活状态
        user.email_active = True
        user.save()
        # 5.返回响应
        return Response({'msg':'ok'})

"""
当用户填写完信息之后,点击保存,前端发送一个ajax请求把参数传递给后端
这个时候user信息以jwt的方式传递过来
1.接收数据
2.校验参数
3.数据保存
4.返回响应
POST   /users/addresses/

"""
from rest_framework.generics import CreateAPIView,ListAPIView
from .serializers import AddressSerializer
from .models import Address
class AddressView(CreateAPIView):

    serializer_class = AddressSerializer

    #query_set 在CreateAPIView中使用不到,它是查询结果集的

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from .serializers import AddressTitleSerializer

class AddressViewSet(mixins.ListModelMixin,mixins.CreateModelMixin,mixins.UpdateModelMixin,GenericViewSet):
    """
    用户地址新增与修改
    list GET: /users/addresses/
    create POST: /users/addresses/
    destroy DELETE: /users/addresses/
    action PUT: /users/addresses/pk/status/
    action PUT: /users/addresses/pk/title/
    """

    #制定序列化器
    serializer_class = AddressSerializer
    #添加用户权限
    permission_classes = [IsAuthenticated]
    #由于用户的地址有存在删除的状态,所以我们需要对数据进行筛选
    def get_queryset(self):
        return self.request.user.addresses.filter(is_deleted=False)

    def create(self, request, *args, **kwargs):
        """
        保存用户地址数据
        """
        count = request.user.addresses.count()
        if count >= 20:
            return Response({'message':'保存地址数量已经达到上限'},status=status.HTTP_400_BAD_REQUEST)

        return super().create(request,*args,**kwargs)

    def list(self, request, *args, **kwargs):
        """
        获取用户地址列表
        """
        # 获取所有地址
        queryset = self.get_queryset()
        # 创建序列化器
        serializer = self.get_serializer(queryset, many=True)
        user = self.request.user
        # 响应
        return Response({
            'user_id': user.id,
            'default_address_id': user.default_address_id,
            'limit': 20,
            'addresses': serializer.data,
        })

    def destroy(self, request, *args, **kwargs):
        """
        处理删除
        """
        address = self.get_object()

        # 进行逻辑删除
        address.is_deleted = True
        address.save()

        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(methods=['put'], detail=True)
    def title(self, request, pk=None, address_id=None):
        """
        修改标题
        """
        address = self.get_object()
        serializer = AddressTitleSerializer(instance=address, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    @action(methods=['put'], detail=True)
    def status(self, request, pk=None, address_id=None):
        """
        设置默认地址
        """
        address = self.get_object()
        request.user.default_address = address
        request.user.save()
        return Response({'message': 'OK'}, status=status.HTTP_200_OK)

"""
redis 数据类型
string      key:value
list        list_key:value1  value2 value3 value2
hash        hash_key:key:value key value
set         set_key:value2 value1 value4
zset        zset_key:value1 value2 value3

1.登录用户才可以访问用户浏览记录接口
2.我们只记录登录用户的浏览记录
3.我们用redis来保存浏览历史记录,列表
4.我们应该在用户访问商品详情的时候,记录用户浏览记录

添加浏览记录 POST     users/browerhistories/
    当用户访问商品详情的时候,前端应该发送一个ajax请求,
    这个请求应该包含商品id,用户信息(JWT)

    后端应该
    1.接收数据,校验数据
    2.保存数据
    3.返回响应

获取浏览记录 GET
    1.登录用户访问
    2.我们从redis中获取数据
    3.根据id查询商品详细信息
    4.返回响应


"""
#APIView
#GenericAPIView
#CreateAPIView
from .serializers import UserHistorySerializer
from django_redis import get_redis_connection
from .serializers import SKUSerializer
class UserHistoryView(APIView):

    permission_classes = [IsAuthenticated]

    def post(self,request):

        user = request.user
        # 1.接收数据,校验数据
        serializer = UserHistorySerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 2.保存数据 --->redis
        sku_id = serializer.validated_data.get('sku_id')
        #2.1连接redis
        redis_conn = get_redis_connection('history')

        #2.2先把sku_id在列表中的数据删除
        redis_conn.lrem('history_%s'%user.id,0,sku_id)

        #2.3写入redis的列表中
        # history_user_id: [1,2,3]
        redis_conn.lpush('history_%s'%user.id,sku_id)

        #2.4通过ltrim对列表进行修剪,保留5个记录
        redis_conn.ltrim('history_%s'%user.id,0,4)

        # 3.返回响应
        return Response(serializer.data)

    def get(self,request):

        # 1.登录用户访问
        user = request.user

        # 2.我们从redis中获取数据
        redis_conn = get_redis_connection('history')
        sku_ids = redis_conn.lrange('history_%s'%user.id,0,4)

        # 3.根据id查询商品详细信息
        #通过in去取数据的时候顺序会错乱,所以我们不用in
        # skus = SKU.objects.filter(id__in=sku_ids)
        skus = []
        for sku_id in sku_ids:
            sku = SKU.objects.get(pk=sku_id)
            skus.append(sku)

        serializer = SKUSerializer(skus,many=True)
        # 4.返回响应
        return Response(serializer.data)

from utils.cart import merge_cookie_to_redis
from rest_framework_jwt.views import ObtainJSONWebToken

class UserAuthorizationView(ObtainJSONWebToken):

    def post(self, request):
        # 调用jwt扩展的方法，对用户登录的数据进行验证
        response = super().post(request)

        # 如果用户登录成功，进行购物车数据合并
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            # 表示用户登录成功
            user = serializer.validated_data.get("user")
            # 合并购物车
            #merge_cart_cookie_to_redis(request, user, response)
            response = merge_cookie_to_redis(request, user, response)

        return response


